﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace N3P.WCF.Proxyless.FullDuplex.Silverlight
{
    /// <summary>
    /// Represents an Address/Binding/Contract pairing for establishing WCF connections
    /// </summary>
    internal class AddressBindingContract
    {

        /// <summary>
        /// Creates a new <see cref="AddressBindingContract"/>
        /// </summary>
        /// <param name="address">The address of the remote service</param>
        /// <param name="contract">The contract the service implements</param>
        /// <param name="bindingType">The full name of the type of the binding that is used by the endpoint</param>
        /// <param name="bindingConfiguration">The name of the binding configuration to use</param>
        /// <param name="name">The name of the endpoint</param>
        public AddressBindingContract(string address, string contract, string bindingType, string bindingConfiguration, string name="")
        {
            Name = name;

            if(string.IsNullOrWhiteSpace(bindingConfiguration))
            {
                var casedBindingType = bindingType.Substring(0, 1).ToUpper() + bindingType.Substring(1);
                var bType = WcfClientBase.FindType(casedBindingType);
                Binding = (Binding) Activator.CreateInstance(bType);
            }
            else
            {
                Binding = WcfClientBase.BindingConfigurations[bindingConfiguration];
            }

            Contract = WcfClientBase.FindType(contract);
            
            if(Contract == null)
            {
                throw new TypeLoadException("Could not locate type " + contract);
            }

            Address = new EndpointAddress(address);
        }

        /// <summary>
        /// Creates a new <see cref="AddressBindingContract"/>
        /// </summary>
        /// <param name="address">The address to use</param>
        /// <param name="binding">The binding to use</param>
        /// <param name="contract">The contract to use</param>
        /// <param name="name">(Optional) The name to use</param>
        public AddressBindingContract(EndpointAddress address, Binding binding, Type contract, string name = "")
        {
            Name = name;
            Binding = binding;
            Address = address;
            Contract = contract;
        }



        /// <summary>
        /// Gets the address of the remote service
        /// </summary>
        public EndpointAddress Address { get; private set; }

        /// <summary>
        /// Gets the <see cref="Binding"/> for the service
        /// </summary>
        public Binding Binding { get; private set; }

        /// <summary>
        /// Gets the contract the service implements
        /// </summary>
        public Type Contract { get; private set; }

        /// <summary>
        /// Gets the name of the endpoint
        /// </summary>
        public string Name { get; private set; }
    }
}
